package com.hrbxlh.util;

import com.hrbxlh.actionImpl.CourseActionImpl;
import com.hrbxlh.enums.DownloadFileEnum;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
//import java.util.zip.ZipEntry;
//import java.util.zip.ZipOutputStream;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;

/**
 * -------------------------------------------------------
 * Copyright (c) 2017, 鑫联华信息科技股份有限公司
 * All rights reserved.
 * FileName：FileDownloadZipUtil.java
 * Description：文件批量下载为zip的工具类
 * History：
 * Date           Author               Desc
 * 2017-10-25	   xzx                  建立
 * -------------------------------------------------------
 */
public class FileDownloadZipUtil {

    static ApplicationContext app = new ClassPathXmlApplicationContext(
            "classpath:spring-mybatis.xml");
    static CourseActionImpl courseActionImpl = (CourseActionImpl) app
            .getBean("courseActionImpl");
    private static final org.slf4j.Logger log = LoggerFactory.getLogger(FileDownloadZipUtil.class);

    /**
     * @description 批量下载各种课件的方法,下载为zip文件,并删除，
     * @param zip文件名，不要后缀
     * @param zip临时文件存放路径  eg:d:/123
     * @param 要下载的所有文件名全路径
     * */
    public static void downloadZipUtil(String zipName, String zipExistPath, String[] fileNameArr, HttpServletRequest request, HttpServletResponse response) throws IOException {
        //判断文件夹是否存在，不存在就创建
        checkFilderExistsUtil(zipExistPath);
        String pathUrl = zipExistPath+"/"+new SessionValues().getSessionValues(new String[] {"stuorteaId"}, request, "userMsg").get("stuorteaId").toString();
        //添加工号文件夹 download/工号/zip文件
        checkFilderExistsUtil(pathUrl);
        //创建临时zip文件
        buildZip(request, zipName, pathUrl, fileNameArr);
        //浏览器下载
       // downloadZipUse(zipName + ".zip", pathUrl + "\\" + zipName + ".zip", request, response, pathUrl);
    }

    /**
     * @description 批量下载作业or实验报告、试卷等的方法,下载为zip文件,并删除，
     * @param zip文件名，不要后缀
     * @param zip临时文件存放路径  eg:d:/123
     * @param 要下载的所有文件名全路径
     * */
    public static Map<String,Object> downloadWorkZipUtil(String zipExistPath, List<Map<String,Object>> fileNameArr, HttpServletRequest request, HttpServletResponse response, List<Map<String,Object>> courseList, Map<String, Object> paramMap) throws Exception {
        //判断文件夹是否存在，不存在就创建
        checkFilderExistsUtil(zipExistPath);
        String teaUrl = zipExistPath+"/"+String.valueOf(paramMap.get("teaId"));
        //添加工号文件夹 download/工号/zip文件
        checkFilderExistsUtil(teaUrl);
        String pathUrl = teaUrl+"/"+String.valueOf(paramMap.get("stuorteaId"));
        checkFilderExistsUtil(pathUrl);
        //创建临时zip文件
        Map<String,Object> returnMap = buildWorkZip(request, pathUrl,teaUrl , fileNameArr,courseList,String.valueOf(paramMap.get("stuorteaId")),Integer.parseInt(String.valueOf(paramMap.get("downloadType"))));
        //将打成.zip的原文件夹删除
        FileUpload.delFolder(pathUrl);
        //浏览器下载
        // downloadZipUse(zipName + ".zip", pathUrl + "\\" + zipName + ".zip", request, response, pathUrl);
        return returnMap;
    }

    /**
     * @description创建临时zip文件
     * @param zip文件名
     * @param zip文件存在服务器的路径文件夹，不需要最后一层/
     * @param 要下载的所有文件全路径，每个文件都要全路径
     * */
    public static Map<String ,Object> buildWorkZip(HttpServletRequest request,String zipExistPath,String teaUrl, List<Map<String,Object>> fileNameArr,List<Map<String,Object>> courseList,String stuorteaId,int downloadType) throws Exception {
        Map<String ,Object> returnMap = new HashMap<>();
        //压缩文件初始设置
        String path = zipExistPath;
        String coursePath = zipExistPath;
        String zipStr = "";
        if(downloadType== DownloadFileEnum.DOWNLOAD_HOMEWORK.getCode()){
            zipStr = DownloadFileEnum.DOWNLOAD_HOMEWORK.getMessage();
        }if(downloadType==DownloadFileEnum.DOWNLOAD_TEST.getCode()){
            zipStr = DownloadFileEnum.DOWNLOAD_TEST.getMessage();
        }if(downloadType==DownloadFileEnum.DOWNLOAD_EXAM.getCode()){
            zipStr = DownloadFileEnum.DOWNLOAD_EXAM.getMessage();
        }
        String fileName = stuorteaId+"-"+zipStr+".zip";
        // 拼接zip文件
        String filePath = teaUrl+"/"+fileName;
        returnMap.put("fileName",fileName);
        Logger logger = Logger.getLogger(FileDownloadZipUtil.class.getName());
        logger.info("要下载的zip文件名为："+filePath);
        try {
            Map<String,Object> paramMap = new HashMap<>();
            for(int i=0;i<courseList.size();i++){
                File[] files = null;
                String[] fileNames = null;
                boolean flag = false;
                String fileSource = "";
                Integer count=0;
                for (Map<String,Object> map :fileNameArr ) {
                    if (map.get("courseId").toString().equals(String.valueOf(courseList.get(i).get("courseId")))){
                        count++;
                    }
                }
                fileNames=new String[count];
                files=new File[count];
                int index=0;
                for(int j=0;j<fileNameArr.size();j++){
                    if(String.valueOf(courseList.get(i).get("courseId")).equals(String.valueOf(fileNameArr.get(j).get("courseId")))){
                        if(Integer.parseInt(String.valueOf(fileNameArr.get(j).get("courseId")))!=0){
                            if(index==0){
                                paramMap.put("courseId",fileNameArr.get(j).get("courseId"));
                                Map<String,Object> courseMap = courseActionImpl.getCourseDetail(paramMap,request);
                                String courseName= String.valueOf(courseMap.get("courseName"));
                                //判断文件夹是否存在，不存在就创建
                                fileSource = coursePath+"/"+courseName+"/";
                                checkFilderExistsUtil(fileSource);
                            }
//                            files = new File[index+1];
                            files[index]=new File(String.valueOf(fileNameArr.get(j).get("path")));//获取全部文件全路径
//                            fileNames = new String[index+1];
                            fileNames[index] = new String(String.valueOf(fileNameArr.get(j).get("fileName")));
                            flag = true;
                            index++;
                        }

                    }
                }
                if(!flag){
                    files = null;
                }
                //将每个课的文件放到每个课的文件夹里然后在将所有课的文件加内容写到zip里最后打成.zip包
                if(files!=null&&files.length!=0){
                    //将所有需要下载的文件都写入临时zip文件
                    for (int k = 0; k < files.length; k++) {
                        String sourceUrl = fileSource+"/"+fileNames[k];
                        File destFile = new File(sourceUrl);
                        FileUtils.copyInputStreamToFile(new FileInputStream(files[k]),destFile);// 复制临时文件到指定目录下
                    }
                }

            }
            //将生成好的文件夹打成.zip包
            createZip(path, filePath);
        }catch(FileNotFoundException fe){
            fe.printStackTrace();
            throw fe;
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        }
        return returnMap;
    }

    /**
     * 创建ZIP文件
     * @param sourcePath 文件或文件夹路径
     * @param zipPath 生成的zip文件存在路径（包括文件名）
     */
    public static void createZip(String sourcePath, String zipPath) {
        FileOutputStream fos = null;
        ZipOutputStream zos = null;
        try {
            fos = new FileOutputStream(zipPath);
            zos = new ZipOutputStream(fos);
            zos.setEncoding("gbk");//此处修改字节码方式。
            //createXmlFile(sourcePath,"293.xml");
            writeZip(new File(sourcePath), "", zos);
        } catch (FileNotFoundException e) {
            log.error("创建ZIP文件失败",e);
        } finally {
            try {
                if (zos != null) {
                    zos.close();
                }
            } catch (IOException e) {
                log.error("创建ZIP文件失败",e);
            }

        }
    }

    private static void writeZip(File file, String parentPath, ZipOutputStream zos) {
        if(file.exists()){
            if(file.isDirectory()){//处理文件夹
                parentPath+=file.getName()+File.separator;
                File [] files=file.listFiles();
                if(files.length != 0)
                {
                    for(File f:files){
                        writeZip(f, parentPath, zos);
                    }
                }
                else
                {       //空目录则创建当前目录
                    try {
                        zos.putNextEntry(new ZipEntry(parentPath));
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }else{
                FileInputStream fis=null;
                try {
                    fis=new FileInputStream(file);
                    ZipEntry ze = new ZipEntry(parentPath + file.getName());
                    zos.putNextEntry(ze);
                    byte [] content=new byte[1024];
                    int len;
                    while((len=fis.read(content))!=-1){
                        zos.write(content,0,len);
                        zos.flush();
                    }

                } catch (FileNotFoundException e) {
                    log.error("创建ZIP文件失败",e);
                } catch (IOException e) {
                    log.error("创建ZIP文件失败",e);
                }finally{
                    try {
                        if(fis!=null){
                            fis.close();
                        }
                    }catch(IOException e){
                        log.error("创建ZIP文件失败",e);
                    }
                }
            }
        }
    }

    /**
     * @description 判断文件夹是否存在，不存在就创建
     * @param 文件夹路径无最后一级/
     * */
    /**
     * @description 判断给的文件路径存不存在，不存在新建，存在就看有没有最后一级的/ 或者\\
     *
     * */
    public static boolean checkFilderExistsUtil(String path){
        boolean result = false;
        File filePath = new File(path);
        //如果没有这个文件夹，新建
        if(!filePath.exists() || !filePath.isDirectory()){
            filePath.mkdir();
        }
        result = true;
        return result;
    }


    /**
     * @description创建临时zip文件
     * @param zip文件名
     * @param zip文件存在服务器的路径文件夹，不需要最后一层/
     * @param 要下载的所有文件全路径，每个文件都要全路径
     * */
    public static void buildZip(HttpServletRequest request, String zipName, String zipExistPath, String[] fileNameArr) throws IOException {
        //压缩文件初始设置
        String path = zipExistPath;
        String base_name = zipName;
        // 拼接zip文件
        String fileZip = base_name + ".zip";
        Logger logger = Logger.getLogger(FileDownloadZipUtil.class.getName());
        logger.info("要下载的zip文件名为："+fileZip);
        //之后用来生成zip文件
        String filePath = path+"/" + fileZip;
        //filePathArr为要下载的文件的全部信息，通过数据库查询所得出的文件路径集合（具体到后缀）
        //test
        //fileNameArr = new String[] {"d:/zaq.pptx","d:/cvb.html"};
        //test end
        File[] files = new File[fileNameArr.length];
        for(int i=0;i<fileNameArr.length;i++){
            files[i]=new File(fileNameArr[i]);//获取全部文件全路径
        }
        // 创建临时压缩文件
        try {
            new File(filePath).createNewFile();
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));
            ZipOutputStream zos = new ZipOutputStream(bos);
            //获得浏览器代理信息
            //final String userAgent = request.getHeader("USER-AGENT");
            //if(StringUtils.contains(userAgent, "MSIE")||StringUtils.contains(userAgent,"Trident")){//IE浏览器
            zos.setEncoding("UTF-8");
            //}else if(StringUtils.contains(userAgent, "Mozilla")){//google,火狐浏览器
            //    zos.setEncoding("UTF8");//  ISO8859-1
            //}else{
            //    zos.setEncoding("UTF8");//其他浏览器
            //}
            //测试浏览器编码
            ZipEntry ze = null;
            //将所有需要下载的文件都写入临时zip文件
            for (int i = 0; i < files.length; i++) {
                BufferedInputStream bis = new BufferedInputStream(new FileInputStream(files[i]));
                ze = new ZipEntry(files[i].getName());
                zos.putNextEntry(ze);
                int s = -1;
                while ((s = bis.read()) != -1) {
                    zos.write(s);
                }
                bis.close();
            }
            zos.flush();
            zos.close();
        }catch(FileNotFoundException fe){
            fe.printStackTrace();
            throw fe;
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * 下载文件信息并删除临时文件
     * 要下载的zip的文件名
     * 要下载的zip的全路径文件信息
     * */
    public static void downloadZipUse(String fileZip,String filePath, HttpServletRequest request, HttpServletResponse response, String delDir) throws IOException {

        //获得浏览器代理信息
        final String userAgent = request.getHeader("USER-AGENT");
        //判断浏览器代理并分别设置响应给浏览器的编码格式
        String finalFileName = null;
        if(StringUtils.contains(userAgent, "MSIE")||StringUtils.contains(userAgent,"Trident")){//IE浏览器
            finalFileName = URLEncoder.encode(fileZip,"UTF8");
        }else if(StringUtils.contains(userAgent, "Mozilla")){//google,火狐浏览器
            finalFileName = new String(fileZip.getBytes(), "ISO8859-1");
        }else{
            finalFileName = URLEncoder.encode(fileZip,"UTF8");//其他浏览器
        }
        response.setContentType("application/x-download");//告知浏览器下载文件，而不是直接打开，浏览器默认为打开
        //下载文件的名称
        response.setHeader("Content-Disposition" ,"attachment;filename=\"" +finalFileName+ "\"");
        ServletOutputStream servletOutputStream=response.getOutputStream();
        DataOutputStream temps = new DataOutputStream(servletOutputStream);
        //浏览器下载文件的路径
        DataInputStream in = new DataInputStream(new FileInputStream(filePath));
        byte[] b = new byte[2048];
        //之后用来删除临时压缩文件
        File reportZip=new File(filePath);
        try {
            while ((in.read(b)) != -1) {
                temps.write(b);
            }
            temps.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(temps!=null) temps.close();
            if(in!=null) in.close();
            //删除服务器本地产生的临时压缩文件
            if(reportZip!=null) reportZip.delete();
            //删除此次生成的文件夹目录
            if(new File(filePath)!=null) new File(delDir).delete();
            servletOutputStream.close();
        }
    }



    @RequestMapping(value = "/test111", method = RequestMethod.GET)
    public void test111(HttpServletRequest request, HttpServletResponse response) throws IOException {

        //this.downloadZip("哈哈哈", "d:/123", new String[] {"d:/qaz.pptx","d:/cvb.html"}, request, response);

    }

    public static void main(String[] args) {
    }


}
